<?php
class JSONDBSD {
    private $data;
    private $cache;
    private $lockFile;

    public function __construct($filename) {
        $this->lockFile = $filename . '.lock';
        $this->loadData($filename);
    }

    private function loadData($filename) {
        $json = $this->fileReadSafe($filename);
        if ($json !== false) {
            $this->data = json_decode($json, true);
            $this->cache = $this->data;
        } else {
            $this->data = [];
            $this->cache = [];
        }
    }

    public function saveData($filename) {
        $json = json_encode($this->data);
        $this->fileWriteSafe($filename, $json);
    }

    public function insert($table, $data) {
        if (!isset($this->data[$table])) {
            $this->data[$table] = [];
        }
        $this->data[$table][] = $data;
        $this->cache[$table][] = $data;
        $this->saveData($this->lockFile); // 保存数据到文件中
    }

    public function delete($table, $condition) {
        if (isset($this->data[$table])) {
            $this->data[$table] = array_filter($this->data[$table], function ($row) use ($condition) {
                return $this->checkConditions($row, $condition);
            });
            $this->cache[$table] = $this->data[$table];
            $this->saveData($this->lockFile); // 保存数据到文件中
        }
    }

    public function select($table, $condition) {
        if (isset($this->cache[$table])) {
            $result = [];
            foreach ($this->cache[$table] as $row) {
                if ($this->checkConditions($row, $condition)) {
                    $result[] = $row;
                }
            }
            return $result;
        } else {
            return [];
        }
    }

    public function update($table, $condition, $data) {
        if (isset($this->data[$table])) {
            foreach ($this->data[$table] as &$row) {
                if ($this->checkConditions($row, $condition)) {
                    foreach ($data as $key => $value) {
                        $row[$key] = $value;
                    }
                }
            }
            $this->cache[$table] = $this->data[$table];
            $this->saveData($this->lockFile); // 保存数据到文件中
        }
    }

    private function checkConditions($row, $conditions) {
        $result = true;

        foreach ($conditions as $field => $comparison) {
            $comparisonOperator = key($comparison);
            $comparisonValue = $comparison[1];
            switch ($comparisonOperator) {
                case '=':
                    $comparisonResult = ($row[$field] === $comparisonValue);
                    break;
                case '!=':
                    $comparisonResult = ($row[$field] !== $comparisonValue);
                    break;
                case '<':
                    $comparisonResult = ($row[$field] < $comparisonValue);
                    break;
                case '>':
                    $comparisonResult = ($row[$field] > $comparisonValue);
                    break;
                case '<=':
                    $comparisonResult = ($row[$field] <= $comparisonValue);
                    break;
                case '>=':
                    $comparisonResult = ($row[$field] >= $comparisonValue);
                    break;
                case 'contains':
                    $comparisonResult = (strpos($row[$field], $comparisonValue) !== false);
                    break;
                default:
                    $comparisonResult = false;
                    break;
            }

            $result = $result && $comparisonResult;
        }

        return $result;
    }

    private function fileReadSafe($file, $timeout = 3) {
        if (!$file || !file_exists($file)) return false;
        $fp = @fopen($file, 'r');
        if (!$fp) return false;
        $startTime = microtime(true);
        do {
            $locked = flock($fp, LOCK_SH);
            if (!$locked) {
                usleep(mt_rand(1, 50) * 1000);
            }
        } while ((!$locked) && ((microtime(true) - $startTime) < $timeout));
        if ($locked && filesize($file) >= 0) {
            $result = @fread($fp, filesize($file));
            flock($fp, LOCK_UN);
            fclose($fp);
            if (filesize($file) == 0) {
                return '';
            }
            return $result;
        } else {
            flock($fp, LOCK_UN);
            fclose($fp);
            return false;
        }
    }

    private function fileWriteSafe($file, $buffer, $timeout = 3) {
        clearstatcache();
        if (strlen($file) == 0 || !$file || !file_exists($file)) return false;
        $fp = fopen($file, 'r+');
        $startTime = microtime(true);
        do {
            $locked = flock($fp, LOCK_EX);
            if (!$locked) {
                usleep(mt_rand(1, 50) * 1000);
            }
        } while ((!$locked) && ((microtime(true) - $startTime) < $timeout));
        if ($locked) {
            $tempFile = $file . '.temp';
            $result = file_put_contents($tempFile, $buffer, LOCK_EX);
            if (!$result || !file_exists($tempFile)) {
                flock($fp, LOCK_UN);
                fclose($fp);
                return false;
            }
            @unlink($tempFile);

            ftruncate($fp, 0);
            rewind($fp);
            $result = fwrite($fp, $buffer);
            flock($fp, LOCK_UN);
            fclose($fp);
            clearstatcache();
            return $result;
        } else {
            flock($fp, LOCK_UN);
            fclose($fp);
            return false;
        }
    }
}

?>